/*
 * Copyright (c) United Binary LLC.  All rights reserved.
 * 
 * This code is licensed under the MIT License
 * 
 * SEE: http://harnessit.codeplex.com/license
 * 
 */
using System;
using System.Diagnostics;
using System.Windows.Forms;
using UnitedBinary.HarnessIt.SharedTypes;
using UnitedBinary.UnitTests.Framework;

namespace UnitedBinary.HarnessIt.TestEngine.Local
{
	[TestEngine]
	public class LocalExecutionEngine : ITestEngine
	{
		#region Member Variables

		private string name = "HarnessIt Local Test Engine";

		private string desc =
			"HarnessIt Local Test Engine is used to run tests directly in the context of HarnessIt on the same machine.";

		private string company = "United Binary, LLC.";

		private object target;

		#endregion

		#region ITestEngine implementation

		public string Initialize()
		{
			target = null;
			return "Local Engine successfully initialized.\n";
		}

		public string Shutdown()
		{
			target = null;
			return "Local Engine shutdown complete.";
		}

		public void RunTest(Method method)
		{
			bool isRenew = method.ParentClass.ExecutionMode == TestExecutionModes.Renew;
			bool needsNewInstance = target == null || target.GetType() != method.ParentClass.Type;

			Stopwatch sw = new Stopwatch();
			try
			{
				if ( isRenew || needsNewInstance )
				{
					target = Activator.CreateInstance( method.ParentClass.Type );
				}

				sw.Start();
				method.RunTest( target );
			}
			finally
			{
				sw.Stop();
				method.RunningTime = sw.Elapsed.TotalSeconds;

				DisposeOfInstanceIfAvailable( method, isRenew );
			}
		}

		private void DisposeOfInstanceIfAvailable(Method method, bool isRenew)
		{
			try
			{
				IDisposable dispose = target as IDisposable;
				if ( isRenew && dispose != null )
				{
					dispose.Dispose();
				}
			}
			catch ( Exception ex )
			{
				string msg = string.Format( "HarnessIt: Error disposing of type {0}: {1}",
				                            method.ParentClass.Type.FullName, ex );
				Trace.WriteLine( msg );
				method.TestRecord.WriteLine( msg );
			}
		}

		public bool SettingsDialogAvailable
		{
			get { return false; }
		}

		public DialogResult ShowSettingsDialog()
		{
			throw new Exception( "No settings dialog is available for this engine." );
		}

		public string GetSettings()
		{
			// Nothing to do here, no custom settings.
			return "";
		}

		public void LoadSettings(string settings)
		{
			// Nothing to do here, no custom settings.
		}

		public string Name
		{
			get { return name; }
		}

		public string Description
		{
			get { return desc; }
		}

		public string Company
		{
			get { return company; }
		}

		#endregion
	}
}